home *** CD-ROM | disk | FTP | other *** search
/ NeXTSTEP 3.3 (Developer)…68k, x86, SPARC, PA-RISC] / NeXTSTEP 3.3 Dev Intel.iso / NextDeveloper / Source / GNU / cc / machopic.c < prev    next >
C/C++ Source or Header  |  1994-05-13  |  20KB  |  877 lines

  1. /* NeXTSTEP mach-o pic support functions.
  2.    Copyright (C) 1992, 1994 Free Software Foundation, Inc.
  3.  
  4. This file is part of GNU CC.
  5.  
  6. GNU CC is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2, or (at your option)
  9. any later version.
  10.  
  11. GNU CC is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GNU CC; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. /* 
  21.  * flag_pic = 1 ... generate only indirections
  22.  * flag_pic = 2 ... generate indirections and pure code
  23.  */
  24.  
  25.  
  26. /* 
  27.  *   This module assumes that (const (symbol_ref "foo")) is
  28.  *   a legal pic reference, which will not be changed.
  29.  */
  30. #include "config.h"
  31.  
  32. #ifdef MACHO_PIC
  33.  
  34. #include "tree.h"
  35. #include "rtl.h"
  36. #include "output.h"
  37. #include "machopic.h"
  38. #include "insn-config.h"
  39. #include "insn-flags.h"
  40.  
  41. #include <stdio.h>
  42.  
  43. /* Answer if the symbol named IDENT is known to be defined in 
  44.    the current module.  It is critical, that it *never* says
  45.    something is defined, when it isn't.  However, it is ok to be 
  46.    sloppy on the other end of the scale, it will only generate 
  47.    worse code than if it guessed correct. */
  48.  
  49. static tree machopic_defined_list = 0;
  50.  
  51. extern int flag_dave_indirect;
  52.  
  53. enum machopic_addr_class
  54. machopic_classify_ident (ident)
  55.      tree ident;
  56. {
  57.   char *name = IDENTIFIER_POINTER (ident);
  58.   int lprefix = (name[0] == '*' 
  59.          && (name[1] == 'L'
  60.              || (name[1] == '"' && name[2] == 'L'))); 
  61.     
  62.   tree temp, decl  = (tree)lookup_name (ident);
  63.  
  64.   if (!decl)
  65.     {
  66.       if (lprefix)
  67.     {
  68.       char *name = IDENTIFIER_POINTER (ident);
  69.       while (*name++)
  70.         {
  71.           if (! strncmp (name, "$stub\0", 6))
  72.         return MACHOPIC_DEFINED_FUNCTION;
  73.         }
  74.       return MACHOPIC_DEFINED_DATA;
  75.     }
  76.  
  77.       for (temp = machopic_defined_list;
  78.        temp != NULL_TREE; 
  79.        temp = TREE_CHAIN (temp))
  80.     {
  81.       if (ident == TREE_VALUE (temp))
  82.         return MACHOPIC_DEFINED_DATA;
  83.     }
  84.  
  85.       return MACHOPIC_UNDEFINED;
  86.     }
  87.  
  88.   /* variable declarations */
  89.   else if (TREE_CODE (decl) == VAR_DECL)
  90.     {
  91.       if ((DECL_INITIAL (decl) 
  92.        || TREE_STATIC (decl))
  93.       && ! TREE_PUBLIC (decl))
  94.     return MACHOPIC_DEFINED_DATA;
  95.     }
  96.  
  97.   /* function declarations */
  98.   else if (TREE_CODE (decl) == FUNCTION_DECL)
  99.     {
  100.       if (TREE_STATIC (decl)
  101.       || TREE_ASM_WRITTEN (decl))
  102.     return MACHOPIC_DEFINED_FUNCTION;
  103.     }
  104.  
  105.   for (temp = machopic_defined_list;
  106.        temp != NULL_TREE; 
  107.        temp = TREE_CHAIN (temp))
  108.     {
  109.       if (ident == TREE_VALUE (temp))
  110.     if (TREE_CODE (decl) == FUNCTION_DECL)
  111.       return MACHOPIC_DEFINED_FUNCTION;
  112.     else
  113.       return MACHOPIC_DEFINED_DATA;
  114.     }
  115.   
  116.   if (TREE_CODE (decl) == FUNCTION_DECL)
  117.     {
  118.       if (lprefix)
  119.     return MACHOPIC_DEFINED_FUNCTION;
  120.       else
  121.     return MACHOPIC_UNDEFINED_FUNCTION;
  122.     }
  123.   else
  124.     {
  125.       if (lprefix)
  126.     return MACHOPIC_DEFINED_DATA;
  127.       else
  128.     return MACHOPIC_UNDEFINED_DATA;
  129.     }
  130. }
  131.  
  132.      
  133. enum machopic_addr_class
  134. machopic_classify_name (name)
  135.      char *name;
  136. {
  137.   return machopic_classify_ident (get_identifier (name));
  138. }
  139.  
  140. int
  141. machopic_ident_defined_p (ident)
  142.      tree ident;
  143. {
  144.   switch (machopic_classify_ident (ident))
  145.     {
  146.     case MACHOPIC_UNDEFINED:
  147.     case MACHOPIC_UNDEFINED_DATA:
  148.     case MACHOPIC_UNDEFINED_FUNCTION:
  149.       return 0;
  150.     default:
  151.       return 1;
  152.     }
  153. }
  154.  
  155. int
  156. machopic_name_defined_p (name)
  157.      char *name;
  158. {
  159.   return machopic_ident_defined_p (get_identifier (name));
  160. }
  161.  
  162. void
  163. machopic_define_ident (ident)
  164.      tree ident;
  165. {
  166.   if (!machopic_ident_defined_p (ident))
  167.     machopic_defined_list = 
  168.       perm_tree_cons (NULL_TREE, ident, machopic_defined_list);
  169. }
  170.  
  171. void
  172. machopic_define_name (name)
  173.      char *name;
  174. {
  175.   machopic_define_ident (get_identifier (name));
  176. }
  177.  
  178. /* This is a static to make inline functions work.  The rtx */
  179. /* representing the PIC base symbol allways points to here. */
  180. static char function_base[256];
  181.  
  182. char*
  183. machopic_function_base_name ()
  184. {
  185.   static char *name = 0, *curr_name;
  186.   static int base = 0;
  187.  
  188.   curr_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
  189.  
  190.   if (name != curr_name)
  191.     {
  192.       current_function_uses_pic_offset_table = 1;
  193.  
  194.       if (strchr (curr_name, ' '))
  195.     sprintf (function_base, "*\"L%s$pic_base\"", curr_name);
  196.       else
  197.     sprintf (function_base, "*L%s$pic_base", curr_name);
  198.  
  199.       name = curr_name;
  200.     }
  201.  
  202.   return function_base;
  203. }
  204.  
  205. static tree machopic_non_lazy_pointers = 0;
  206.  
  207. char* 
  208. machopic_non_lazy_ptr_name (name)
  209.      char *name;
  210. {
  211.   tree temp, ident = get_identifier (name);
  212.   
  213.   for (temp = machopic_non_lazy_pointers;
  214.        temp != NULL_TREE; 
  215.        temp = TREE_CHAIN (temp))
  216.     {
  217.       if (ident == TREE_VALUE (temp))
  218.     return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
  219.     }
  220.  
  221.   {
  222.     char buffer[256];
  223.     tree ptr_name;
  224.  
  225.     strcpy (buffer, "*L");
  226.     if (name[0] == '*')
  227.       strcat (buffer, name+1);
  228.     else
  229.       {
  230.     strcat (buffer, "_");
  231.     strcat (buffer, name);
  232.       }
  233.       
  234.     strcat (buffer, "$non_lazy_ptr");
  235.     ptr_name = get_identifier (buffer);
  236.  
  237.     machopic_non_lazy_pointers 
  238.       = perm_tree_cons (ptr_name, ident, machopic_non_lazy_pointers);
  239.  
  240.     return IDENTIFIER_POINTER (ptr_name);
  241.   }
  242. }
  243.  
  244. static tree machopic_stubs = 0;
  245.  
  246. char* 
  247. machopic_stub_name (name)
  248.      char *name;
  249. {
  250.   tree temp, ident = get_identifier (name);
  251.   
  252.   for (temp = machopic_stubs;
  253.        temp != NULL_TREE; 
  254.        temp = TREE_CHAIN (temp))
  255.     {
  256.       if (ident == TREE_VALUE (temp))
  257.     return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
  258.     }
  259.  
  260.   {
  261.     char buffer[256];
  262.     tree ptr_name;
  263.  
  264.     strcpy (buffer, "*L");
  265.     if (name[0] == '*')
  266.       {
  267.     strcat (buffer, name+1);
  268.       }
  269.     else
  270.       {
  271.     strcat (buffer, "_");
  272.     strcat (buffer, name);
  273.       }
  274.  
  275.     strcat (buffer, "$stub");
  276.     ptr_name = get_identifier (buffer);
  277.  
  278.     machopic_stubs = perm_tree_cons (ptr_name, ident, machopic_stubs);
  279.  
  280.     return IDENTIFIER_POINTER (ptr_name);
  281.   }
  282. }
  283.  
  284. /*
  285.  *  Transfrom ORIG, which any data source to the corresponding
  286.  *  source using indirections.  
  287.  */
  288.  
  289. rtx
  290. machopic_indirect_data_reference (orig, reg)
  291.      rtx orig, reg;
  292. {
  293.   rtx ptr_ref = orig;
  294.   
  295.   if (! MACHOPIC_INDIRECT)
  296.     return orig;
  297.  
  298.   if (GET_CODE (orig) == SYMBOL_REF)
  299.     {
  300.       char *name = XSTR (orig, 0);
  301.  
  302.       if (machopic_name_defined_p (name))
  303.     {
  304. #ifdef HAVE_hi_sum
  305.       rtx hi_sum;
  306.       rtx pic_base = gen_rtx (SYMBOL_REF, Pmode, 
  307.                    machopic_function_base_name ());
  308.       rtx offset = gen_rtx (CONST, Pmode, gen_rtx (MINUS, Pmode, orig, pic_base));
  309.  
  310.  
  311.       if (reg == 0) abort ();
  312.  
  313.       hi_sum = gen_rtx (SET, Pmode, HI_SUM_TARGET_RTX,
  314.                 gen_rtx (PLUS, Pmode,
  315.                      pic_offset_table_rtx,
  316.                      gen_rtx (HIGH, Pmode, offset)));
  317.  
  318. #if 1
  319.       emit_insn (hi_sum);
  320. #else
  321.       emit_insn (gen_rtx (PARALLEL, VOIDmode,
  322.                   gen_rtvec (2,
  323.                      hi_sum,
  324.                      gen_rtx (USE, VOIDmode,
  325.                           gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM)))));
  326. #endif
  327.       
  328.       emit_insn (gen_rtx (SET, Pmode, reg,
  329.                   gen_rtx (LO_SUM, Pmode, 
  330.                        HI_SUM_TARGET_RTX, 
  331.                        offset)));
  332.  
  333.       {
  334.         rtx insn = get_last_insn ();
  335.         rtx note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
  336.         
  337.         if (note)
  338.           XEXP (note, 0) = orig;
  339.         else
  340.           REG_NOTES (insn) = gen_rtx (EXPR_LIST, 
  341.                       REG_EQUAL, orig, REG_NOTES (insn));
  342.       }
  343.  
  344.       orig = reg;
  345. #else
  346. #ifdef HAVE_lo_sum
  347.       rtx pic_base = gen_rtx (SYMBOL_REF, Pmode, 
  348.                    machopic_function_base_name ());
  349.  
  350.       if (reg == 0) abort ();
  351.  
  352.       emit_insn (gen_rtx (SET, VOIDmode, reg,
  353.                   gen_rtx (HIGH, Pmode, 
  354.                        gen_rtx (CONST, Pmode, 
  355.                         gen_rtx (MINUS, Pmode,
  356.                              orig, pic_base)))));
  357.       emit_insn (gen_rtx (SET, VOIDmode, reg,
  358.                   gen_rtx (LO_SUM, Pmode, reg, 
  359.                        gen_rtx (CONST, Pmode, 
  360.                         gen_rtx (MINUS, Pmode,
  361.                              orig, pic_base)))));
  362.       emit_insn (gen_rtx (USE, VOIDmode,
  363.                   gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM)));
  364.  
  365.       orig = gen_rtx (PLUS, Pmode, pic_offset_table_rtx, reg);
  366. #endif
  367. #endif
  368.       return orig;
  369.     }
  370.  
  371.  
  372.       if (flag_dave_indirect) 
  373.     {
  374.       extern tree string_type_node;
  375.       extern tree char_array_type_node;
  376.       tree params;
  377.       tree call;
  378.       tree get_addr_decl;
  379.  
  380.       if (reg == 0)
  381.         reg = gen_reg_rtx (Pmode);
  382.  
  383.       get_addr_decl 
  384.         = (tree) lookup_name (get_identifier ("__get_address"));   
  385.       if (get_addr_decl == 0)
  386.         error ("cannot find declaration for __get_address");
  387.  
  388.       params = build_string (strlen (name), name);
  389.       TREE_TYPE (params) = char_array_type_node;
  390.       params = build1 (ADDR_EXPR, string_type_node, params);
  391.       params = build_tree_list (NULL_TREE, params);
  392.  
  393.       call = (tree) build_function_call (get_addr_decl, params);
  394.       expand_call (call, reg, 0);
  395.       RTX_UNCHANGING_P (reg) = 1;
  396.       return reg;
  397.     }
  398.       else /* kevin_indirect */
  399.     {
  400.       ptr_ref = gen_rtx (SYMBOL_REF, Pmode, 
  401.                  machopic_non_lazy_ptr_name (name));
  402.  
  403.  
  404.       /* generating real pure code */
  405. /*
  406.       if (MACHOPIC_PURE)
  407.         ptr_ref = machopic_legitimize_pic_address (ptr_ref, SImode, reg);
  408.     */  
  409.       ptr_ref = gen_rtx (MEM, Pmode, ptr_ref);
  410.       RTX_UNCHANGING_P (ptr_ref) = 1;
  411.     }
  412.  
  413.       return ptr_ref;
  414.     }
  415.   else if (GET_CODE (orig) == CONST)
  416.     {
  417.       rtx base, offset, result;
  418.  
  419.       /* legitimize both operands of the PLUS */
  420.       if (GET_CODE (XEXP (orig, 0)) == PLUS)
  421.     {
  422.       base = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 0), reg);
  423.       orig = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 1),
  424.                            base == reg ? 0 : reg);
  425.     }
  426.       else 
  427.     return orig;
  428.  
  429.       if (MACHOPIC_PURE && GET_CODE (orig) == CONST_INT)
  430.     result = plus_constant_for_output (base, INTVAL (orig));
  431.       else
  432.     result = gen_rtx (PLUS, Pmode, base, orig);
  433.  
  434.       if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
  435.     RTX_UNCHANGING_P (result) = 1;
  436.  
  437.       if (MACHOPIC_JUST_INDIRECT && GET_CODE (base) == MEM)
  438.     {
  439.       if (reg)
  440.         {
  441.           emit_move_insn (reg, result);
  442.           result = reg;
  443.         }
  444.       else
  445.         {
  446.           result = force_reg (GET_MODE (result), result);
  447.         }
  448.     }
  449.  
  450.       return result;
  451.  
  452.     }
  453.   else if (GET_CODE (orig) == MEM)
  454.     {
  455.       XEXP (ptr_ref, 0) = machopic_indirect_data_reference (XEXP (orig, 0), reg);
  456.       return ptr_ref;
  457.     }
  458.   else
  459.     return ptr_ref;
  460. }
  461.  
  462.  
  463. /* 
  464.  *  Transform TARGET (a MEM), which is a function call target, to the
  465.  *  corresponding symbol_stub if nessecary.  Return the a new MEM.
  466.  */
  467.  
  468. rtx
  469. machopic_indirect_call_target (target)
  470.      rtx target;
  471. {
  472.   if (GET_CODE (target) != MEM)
  473.     return target;
  474.   if (MACHOPIC_INDIRECT && GET_CODE (XEXP (target, 0)) == SYMBOL_REF)
  475.     { 
  476.       enum machine_mode mode = GET_MODE (XEXP (target, 0));
  477.       char *name = XSTR (XEXP (target, 0), 0);
  478.       if (!machopic_name_defined_p (name)) 
  479.     {
  480.       if (flag_dave_indirect) 
  481.         {
  482.           XEXP (target, 0) = force_reg (Pmode, XEXP (target, 0));
  483.         }
  484.       else /* kevin_indirect */
  485.         {
  486.           char *stub_name = (char*)machopic_stub_name (name);
  487.           XEXP (target, 0) = gen_rtx (SYMBOL_REF, mode, stub_name);
  488.           RTX_UNCHANGING_P (target) = 1;
  489.         }
  490.     } 
  491.     }
  492.   return target;
  493. }
  494.  
  495.  
  496. rtx
  497. machopic_legitimize_pic_address (orig, mode, reg)
  498.      rtx orig, reg;
  499.      enum machine_mode mode;
  500. {
  501.   rtx pic_ref = orig;
  502.  
  503.   if (! MACHOPIC_PURE)
  504.     return orig;
  505.  
  506.   /* First handle a simple SYMBOL_REF or LABEL_REF */
  507.   if (GET_CODE (orig) == LABEL_REF
  508.       || (GET_CODE (orig) == SYMBOL_REF
  509. #if 0
  510.       && !((machopic_classify_name (XSTR (orig, 0)) 
  511.         == MACHOPIC_DEFINED_FUNCTION)
  512.            && XSTR (orig, 0)[0] == '*')
  513. #endif
  514.       ))
  515.     {
  516.       /* addr(foo) = &func+(foo-func) */
  517.       rtx equiv = orig;
  518.       rtx pic_base;
  519.       orig = machopic_indirect_data_reference (orig, reg);
  520.       if (GET_CODE (orig) == PLUS 
  521.       && GET_CODE (XEXP (orig, 0)) == REG)
  522.     {
  523.       if (reg == 0)
  524.         return force_reg (mode, orig);
  525.  
  526.       emit_move_insn (reg, orig);
  527.       return reg;
  528.     }  
  529.  
  530.       pic_base = gen_rtx (SYMBOL_REF, Pmode, 
  531.               machopic_function_base_name ());
  532.  
  533.       if (GET_CODE (orig) == MEM)
  534.     {
  535.       if (reg == 0)
  536.         abort ();
  537. #ifdef HAVE_lo_sum
  538.       if (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF 
  539.           || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
  540.         {
  541. #ifdef HAVE_hi_sum
  542.           rtx hi_sum;
  543.           rtx offset = gen_rtx (CONST, Pmode,
  544.                     gen_rtx (MINUS, Pmode, XEXP (orig, 0), pic_base));
  545.           
  546.           
  547.           if (reg == 0)
  548.         if (reload_in_progress)
  549.           abort ();
  550.         else
  551.          reg = gen_reg_rtx (Pmode);
  552.           
  553.           hi_sum = gen_rtx (SET, Pmode, HI_SUM_TARGET_RTX,
  554.                 gen_rtx (PLUS, Pmode,
  555.                      pic_offset_table_rtx,
  556.                      gen_rtx (HIGH, Pmode, offset)));
  557.  
  558. #if 1
  559.           emit_insn (hi_sum);
  560. #else
  561.           emit_insn (gen_rtx (PARALLEL, VOIDmode,
  562.                   gen_rtvec (2,
  563.                          hi_sum,
  564.                          gen_rtx (USE, VOIDmode,
  565.                               gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM)))));
  566. #endif
  567.           emit_insn (gen_rtx (SET, VOIDmode, reg,
  568.                   gen_rtx (MEM, GET_MODE (orig),
  569.                        gen_rtx (LO_SUM, Pmode, 
  570.                             HI_SUM_TARGET_RTX, 
  571.                             offset))));
  572.           pic_ref = reg;
  573.  
  574. #else
  575.           emit_insn (gen_rtx (USE, VOIDmode,
  576.                   gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM)));
  577.  
  578.           emit_insn (gen_rtx (SET, VOIDmode, reg,
  579.                   gen_rtx (HIGH, Pmode, 
  580.                        gen_rtx (CONST, Pmode, 
  581.                             gen_rtx (MINUS, Pmode,
  582.                                  XEXP (orig, 0), 
  583.                                  pic_base)))));
  584.           emit_insn (gen_rtx (SET, VOIDmode, reg,
  585.                   gen_rtx (LO_SUM, Pmode, reg, 
  586.                        gen_rtx (CONST, Pmode, 
  587.                             gen_rtx (MINUS, Pmode,
  588.                                  XEXP (orig, 0), 
  589.                                  pic_base)))));
  590.           pic_ref = gen_rtx (PLUS, Pmode,
  591.                  pic_offset_table_rtx, reg);
  592. #endif
  593.         }
  594.       else
  595. #endif
  596.         {
  597.           emit_insn (gen_rtx (USE, VOIDmode,
  598.                   gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM)));
  599.  
  600.           pic_ref = gen_rtx (PLUS, Pmode,
  601.                  pic_offset_table_rtx, 
  602.                  gen_rtx (CONST, Pmode, 
  603.                       gen_rtx (MINUS, Pmode,
  604.                            XEXP (orig, 0), 
  605.                            pic_base)));
  606.         }
  607.       
  608. #ifndef HAVE_hi_sum
  609.       RTX_UNCHANGING_P (pic_ref) = 1;
  610.       emit_move_insn (reg, pic_ref);
  611.       pic_ref = gen_rtx (MEM, GET_MODE (orig), reg);
  612. #endif
  613.     }
  614.       else
  615.     {
  616.  
  617. #ifdef HAVE_lo_sum
  618.       if (GET_CODE (orig) == SYMBOL_REF 
  619.           || GET_CODE (orig) == LABEL_REF)
  620.         {
  621. #ifdef HAVE_hi_sum
  622.           rtx hi_sum;
  623.           rtx offset = gen_rtx (CONST, Pmode,
  624.                     gen_rtx (MINUS, Pmode, orig, pic_base));
  625.           
  626.           if (reg == 0)
  627.         if (reload_in_progress)
  628.           abort ();
  629.         else
  630.          reg = gen_reg_rtx (SImode);
  631.           
  632.           hi_sum = gen_rtx (SET, Pmode, HI_SUM_TARGET_RTX,
  633.                 gen_rtx (PLUS, Pmode,
  634.                      pic_offset_table_rtx,
  635.                      gen_rtx (HIGH, Pmode, offset)));
  636.  
  637. #if 1
  638.           emit_insn (hi_sum);
  639. #else
  640.           emit_insn (gen_rtx (PARALLEL, VOIDmode,
  641.                   gen_rtvec (2,
  642.                          hi_sum,
  643.                          gen_rtx (USE, VOIDmode,
  644.                               gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM)))));
  645. #endif
  646.           emit_insn (gen_rtx (SET, VOIDmode, reg,
  647.                   gen_rtx (LO_SUM, Pmode, 
  648.                        HI_SUM_TARGET_RTX, 
  649.                        offset)));
  650.           pic_ref = reg;
  651. #else
  652.           emit_insn (gen_rtx (SET, VOIDmode, reg,
  653.                   gen_rtx (HIGH, Pmode, 
  654.                        gen_rtx (CONST, Pmode, 
  655.                             gen_rtx (MINUS, Pmode,
  656.                                  orig, pic_base)))));
  657.           emit_insn (gen_rtx (SET, VOIDmode, reg,
  658.                   gen_rtx (LO_SUM, Pmode, reg, 
  659.                        gen_rtx (CONST, Pmode, 
  660.                             gen_rtx (MINUS, Pmode,
  661.                                  orig, pic_base)))));
  662.           pic_ref = gen_rtx (PLUS, Pmode,
  663.                  pic_offset_table_rtx, reg);
  664. #endif
  665.         }
  666.       else
  667. #endif
  668.         if (GET_CODE (orig) == REG)
  669.           {
  670.         return orig;
  671.           }
  672.         else
  673.           {
  674.         emit_insn (gen_rtx (USE, VOIDmode,
  675.                     gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM)));
  676.  
  677.         pic_ref = gen_rtx (PLUS, Pmode,
  678.                    pic_offset_table_rtx, 
  679.                    gen_rtx (CONST, Pmode, 
  680.                         gen_rtx (MINUS, Pmode,
  681.                              orig, pic_base)));
  682.           }
  683.     }
  684.  
  685.       RTX_UNCHANGING_P (pic_ref) = 1;
  686.  
  687.       if (reg == 0)
  688.     return force_reg (mode, pic_ref);
  689.       else
  690.     {
  691.       if (GET_CODE (pic_ref) != REG)
  692.         emit_move_insn (reg, pic_ref);
  693.       else
  694.         reg = pic_ref;
  695.  
  696.       {
  697.         rtx insn = get_last_insn ();
  698.         rtx note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
  699.         
  700.         if (note)
  701.           XEXP (note, 0) = equiv;
  702.         else
  703.           REG_NOTES (insn) = gen_rtx (EXPR_LIST, 
  704.                       REG_EQUAL, equiv, REG_NOTES (insn));
  705.       }
  706.  
  707.       return reg;
  708.     }
  709.     }
  710.  
  711.   else if (GET_CODE (orig) == SYMBOL_REF)
  712.     return orig;
  713.  
  714.   else if (GET_CODE (orig) == PLUS
  715.        && (GET_CODE (XEXP (orig, 0)) == MEM
  716.            || GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
  717.            || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
  718.        && XEXP (orig, 0) != pic_offset_table_rtx
  719.        && GET_CODE (XEXP (orig, 1)) != REG)
  720.     
  721.     {
  722.       rtx base, offset;
  723.       int is_complex;
  724.  
  725.       is_complex = (GET_CODE (XEXP (orig, 0)) == MEM);
  726.  
  727.       base = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
  728.       orig = machopic_legitimize_pic_address (XEXP (orig, 1),
  729.                           Pmode, base == reg ? 0 : reg);
  730.       if (GET_CODE (orig) == CONST_INT)
  731.     {
  732.       pic_ref = plus_constant_for_output (base, INTVAL (orig));
  733.       is_complex = 1;
  734.     }
  735.       else
  736.     {
  737.       pic_ref = gen_rtx (PLUS, Pmode, base, orig);
  738.     }
  739.  
  740.       if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
  741.     RTX_UNCHANGING_P (pic_ref) = 1;
  742.  
  743.       if (reg && is_complex)
  744.     {
  745.       emit_move_insn (reg, pic_ref);
  746.       pic_ref = reg;
  747.     }
  748.       /* Likewise, should we set special REG_NOTEs here?  */
  749.     }
  750.  
  751.   else if (GET_CODE (orig) == CONST)
  752.     {
  753.       return machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
  754.     }
  755.  
  756.   else if (GET_CODE (orig) == MEM
  757.        && GET_CODE (XEXP (orig, 0)) == SYMBOL_REF)
  758.     {
  759.       rtx addr = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
  760.  
  761.       emit_move_insn (reg, gen_rtx (MEM, GET_MODE (orig), addr));
  762.       pic_ref = reg;
  763.     }
  764.  
  765.   return pic_ref;
  766. }
  767.  
  768.  
  769. void
  770. machopic_finish (asm_out_file)
  771.      FILE *asm_out_file;
  772. {
  773.   tree temp;
  774.  
  775.   for (temp = machopic_stubs;
  776.        temp != NULL_TREE; 
  777.        temp = TREE_CHAIN (temp))
  778.     {
  779.       char symb[256];
  780.       char stub[256];
  781.       char *symb_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
  782.       char *stub_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
  783.       
  784.       if (symb_name[0] == '*')
  785.     strcpy (symb, symb_name+1);
  786.       else
  787.     symb[0] = '_', strcpy (symb+1, symb_name);
  788.  
  789.       if (stub_name[0] == '*')
  790.     strcpy (stub, stub_name+1);
  791.       else
  792.     stub[0] = '_', strcpy (stub+1, stub_name);
  793.  
  794.       /* must be in aux-out.c */
  795.       machopic_output_stub (asm_out_file, symb, stub);
  796.       
  797.     }
  798.  
  799.   for (temp = machopic_non_lazy_pointers;
  800.        temp != NULL_TREE; 
  801.        temp = TREE_CHAIN (temp))
  802.     {
  803.       char *symb_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
  804.       char *lazy_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
  805.  
  806.  
  807.       if (machopic_ident_defined_p (TREE_VALUE (temp))) 
  808.     {
  809.       char symb[256];
  810.       
  811.       if (symb_name[0] == '*')
  812.         strcpy (symb, symb_name+1);
  813.       else
  814.         strcpy (symb, symb_name);
  815.  
  816.       readonly_data_section ();
  817.       assemble_label (lazy_name);
  818.       assemble_integer (gen_rtx (SYMBOL_REF, Pmode, symb_name),
  819.                 GET_MODE_SIZE (Pmode), 1);
  820.     }
  821.       else
  822.     {
  823.       machopic_nl_symbol_ptr_section ();
  824.       assemble_name (asm_out_file, lazy_name); 
  825.       fprintf (asm_out_file, ":\n");
  826.  
  827.       fprintf (asm_out_file, "\t.indirect_symbol ");
  828.       assemble_name (asm_out_file, symb_name); 
  829.       fprintf (asm_out_file, "\n");
  830.  
  831.       assemble_integer (const0_rtx, GET_MODE_SIZE (Pmode), 1);
  832.     }
  833.     }
  834. }
  835.  
  836. int 
  837. machopic_operand_p (op)
  838.      rtx op;
  839. {
  840.   if (MACHOPIC_JUST_INDIRECT)
  841.     {
  842.       while (GET_CODE (op) == CONST)
  843.     op = XEXP (op, 0);
  844.  
  845.       if (GET_CODE (op) == SYMBOL_REF)
  846.     return machopic_name_defined_p (XSTR (op, 0));
  847.       else
  848.     return 0;
  849.     }
  850.  
  851.   while (GET_CODE (op) == CONST)
  852.     op = XEXP (op, 0);
  853.  
  854.   if (GET_CODE (op) == MINUS
  855.        && GET_CODE (XEXP (op, 0)) == SYMBOL_REF
  856.        && GET_CODE (XEXP (op, 1)) == SYMBOL_REF
  857.        && machopic_name_defined_p (XSTR (XEXP (op, 0), 0))
  858.        && machopic_name_defined_p (XSTR (XEXP (op, 1), 0)))
  859.     {
  860.       return 1;
  861.     }
  862.  
  863. #if 0
  864.   else if (GET_CODE (op) == SYMBOL_REF
  865.        && (machopic_classify_name (XSTR (op, 0))
  866.            == MACHOPIC_DEFINED_FUNCTION))
  867.     {
  868.       return 1;
  869.     }
  870. #endif
  871.  
  872.   return 0;
  873. }
  874.  
  875. #endif
  876.  
  877.